package com.rn.gypsophila.netty.websocket;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * WebSocket 服务端
 *
 * @author 然诺
 * @date 2021/4/21
 */
@Slf4j
public class WebSocketServer {

    private void run(int port) {
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline()
                                    // 设置log监听器，并且日志级别为debug，方便观察运行流程
                                    .addLast(new LoggingHandler("DEBUG"))
                                    // 设置解码器
                                    .addLast(new HttpServerCodec())
                                    // 聚合器，使用websocket会用到
                                    .addLast(new HttpObjectAggregator(65536))
                                    // 用于大数据的分区传输
                                    .addLast(new ChunkedWriteHandler())
                                    // WebSocket协议处理器
                                    .addLast(new WebSocketServerProtocolHandler("/ws", null, true))
                                    // 自定义的业务handler
                                    .addLast("handler", new WebSocketServerHandler());
                        }
                    });

            Channel channel = bootstrap.bind(port).sync().channel();
            log.info("WebSocket 服务启动成功！port={}", port);
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("WebSocket 服务异常中断..." + e);
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
            log.info("WebSocket 服务已关闭！");
        }
    }

    public static void main(String[] args) {
        new WebSocketServer().run(8081);
    }
}
